-
Notifications
You must be signed in to change notification settings - Fork 0
213. House Robber II #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| return std::max(rob_line(span_without_last), rob_line(span_without_first)); | ||
| } | ||
| private: | ||
| int rob_line(std::span<int>& nums) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::span は軽量な軽量なデータ参照のため、値渡ししてしまってよいと思います。
#include <iostream>
#include <span>
int main()
{
std::span<int> s;
std::cout << sizeof(s) << std::endl;
}16
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sizeofでサイズをチェックする方法も参考になります。ありがとうございます。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
補足すると、 Linux で使用される System V AMD64 ABI では 16 バイトまでのデータはレジスター渡しになるようです。
https://azelpg.gitlab.io/azsky2/note/prog/asm64/22_systemv.html
構造体全体を、2つの 8 byte 値で扱うことが出来る場合、(使用可能なレジスタがあれば) レジスタに格納されます。
2つの 8 byte 値で扱えない場合は、構造体全体がスタックに格納されます。
16 バイトの引数は参照渡しされます。
パフォーマンスが重要な場合については、コンパイラーから出力されるアセンブラを確認したり、マイクロベンチマークを取るのが良いと思います。そうでない場合は、ひとまず値渡しで良いと思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
なるほど、ありがとうございます!参考になります。
| if (nums.size() == 1) { | ||
| return nums[0]; | ||
| } | ||
| auto rob_linearly = [&nums](int begin, int end) -> int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ラムダ式は、長くなると、ソースコードを読むにあたり、目線をラムダ関数の前後で大きく動かさなければならなくなる場合があります。このため、読み手を疲れさせる場合があります。個人的には private なクラス関数としたほうが良いと思います。
ただ、イベントハンドラーを大量に書かなければならない場合や、並列計算フレームワークで計算ロジックをネストさせたい場合、キャプチャーを使いたい場合など、場合に応じて使い分けるのが良いと思います。
| 書いているときは気づきませんでしたが空の配列が渡された時に`nums.begin() + 1`とか`nums.end() - 1`でバグりそうなので`nums.size() == 0`の時の場合分けが欲しいかもしれませんね。 | ||
|
|
||
| ```cpp | ||
| class Solution { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM です。個人的にはこれが一番好きですね。
| } | ||
| return current_max; | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::span は初めて知りました。直接イテレータを渡しても書けそうな気がしたのですが、std::span を介することで vector のように扱えて直感的ということでしょうか?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
おっしゃる通りイテレーターを二つ渡しても書けると思います。利点もその通りだと思います。
イテレーターで渡した場合は
for (const int num : nums) {
...
}が
for (it = begin; it < end; ++it) {
int num = *it
...
}のような形になりますね。
恐らく一つ前の問題(198. House Robber)で入力がvectorとして与えられていたので、その問題で書いたコードを再利用したいという思惑が無意識的に働きstd::spanを選択したんだと思います笑
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
わかりました。ありがとうございます!
問題文:
https://leetcode.com/problems/house-robber-ii/description/